package Controller;

import DataAccess.DataAccessFacade;
import DomainModel.Role;
import DomainModel.User;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.json.JSONArray;
import org.json.JSONObject;

/**
 *
 * @author reyniero
 */
@WebServlet(name = "AdminUsersController", urlPatterns = {"/AdminUsersController"})
public class AdminUsersController extends HttpServlet {

    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("currentUser");

        if (user == null || user.getRole() != Role.ADMIN) {
            request.getRequestDispatcher("/login").forward(request, response);
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);

        String action = request.getParameter("action");

        if (action != null && action.equals("loadUsers")) {
            doLoadUsers(request, response);
        }
        else

        request.getRequestDispatcher("/WEB-INF/grs/adminUsersView.jsp").forward(request, response);
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);

        String actionAddUser = request.getParameter("addUser");
        String actionEditUser = request.getParameter("editUser");
        String actionDeleteUser = request.getParameter("deleteUser");
        String submitUser = request.getParameter("submitUser");
        String cancelSubmitUser = request.getParameter("cancelSubmitUser");

        if (actionAddUser != null) { // ADD user
            request.getRequestDispatcher("/WEB-INF/grs/adminUsersAdd.jsp").forward(request, response);
        }
        if (actionEditUser != null) { // EDIT user
            doEditUser(request, response);
        } else if (cancelSubmitUser != null) { // CANCEL submitting a user
            request.getRequestDispatcher("/WEB-INF/grs/adminUsersView.jsp").forward(request, response);
        } else if (submitUser != null) { // SUBMIT add/edit User
            if (doAddUser(request, response)) {
                request.getRequestDispatcher("/WEB-INF/grs/adminUsersView.jsp").forward(request, response);
            } else {
                request.getRequestDispatcher("/WEB-INF/grs/adminUsersAdd.jsp").forward(request, response);
            }
        }
    }

    protected void doLoadUsers(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            DataAccessFacade daf = DataAccessFacade.getInstance();

            response.setContentType("text/html;charset=UTF-8");
            PrintWriter out = response.getWriter();
            try {
                List<User> allUsers = daf.getAllUsers();
                JSONArray allUsersJson = new JSONArray();

                for (User user : allUsers) {
                    JSONObject userJson = new JSONObject();

                    userJson.put("UserId", user.getUserId());
                    userJson.put("FirstName", user.getFirstName());
                    userJson.put("LastName", user.getLastName());
                    userJson.put("Email", user.getEmail());
                    userJson.put("Username", user.getUsername());
                    userJson.put("RoleId", user.getRole().getRoleId());
                    userJson.put("RoleName", user.getRole().getRoleName());

                    allUsersJson.put(userJson);
                }
                String allUsersStr = allUsersJson.toString();
                out.print(allUsersStr);

            } catch (Exception e) {
            } finally {
                out.close();
            }
        } catch (Exception e) {
        }
    }

    private void doEditUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setAttribute("inputFirstName", request.getParameter("inputFirstName"));
        request.setAttribute("inputLastName", request.getParameter("inputLastName"));
        request.setAttribute("inputUsername", request.getParameter("inputUsername"));
        request.setAttribute("inputEmail", request.getParameter("inputEmail"));
        request.setAttribute("inputRoleId", request.getParameter("inputRoleId"));
        request.setAttribute("inputUserId", request.getParameter("inputUserId"));

        request.getRequestDispatcher("/WEB-INF/grs/adminUsersAdd.jsp").forward(request, response);
    }

    private boolean doAddUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Map<String, String> messages = new HashMap<>();
        request.setAttribute("messages", messages);

        try {
            String strUserId = request.getParameter("inputUserId");
            String strFirstName = request.getParameter("inputFirstName");
            String strLastName = request.getParameter("inputLastName");
            String strEmail = request.getParameter("inputEmail");
            String strUsername = request.getParameter("inputUsername");
            String strPassword = request.getParameter("inputPassword");
            String strRole = request.getParameter("inputRole");
            int userId = (strUserId == null || strUserId.isEmpty()) ? 0 : Integer.valueOf(strUserId);

            request.setAttribute("inputUserId", strUserId);
            request.setAttribute("inputFirstName", strFirstName);
            request.setAttribute("inputLastName", strLastName);
            request.setAttribute("inputEmail", strEmail);
            request.setAttribute("inputUsername", strUsername);
            request.setAttribute("inputRole", strRole);
            request.setAttribute("inputRoleId", Role.valueOf(strRole));

            User user = new User(userId, strUsername, strFirstName, strLastName, strEmail, Role.valueOf(strRole));
            
            String missingFields = user.getMissingFields();
            if (userId == 0 && (strPassword == null || strPassword.isEmpty())) {
                missingFields += missingFields.isEmpty() ? "Password" : ", Password";
            }

            if (!missingFields.isEmpty()) {
                messages.put("error", "Please provide the following fields: " + missingFields);
                return false;
            }

            String validateUsernameResult = user.validateUsername();
            if (!validateUsernameResult.isEmpty()) {
                messages.put("error", validateUsernameResult + missingFields);
                return false;
            }

            if (user.getUserId() == 0 ) { 
                // Validate password if it's a new user
                String validatePasswordResult = user.validatePassword(strPassword);
                if (!validatePasswordResult.isEmpty()) {
                    messages.put("error", validatePasswordResult + missingFields);
                    return false;
                }
            }
            
            DataAccessFacade.getInstance().setUser(user, strPassword);

            String msg = (userId == 0) ? "User added successfully." : "User edited successfully.";
            messages.put("success", msg);
        } catch (Exception e) {
            messages.put("error", "An error occurred adding the user.");
            return false;
        }

        return true;
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

}
